﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace HWLogViewer
{
    public partial class MainForm : Form
    {
        string logfile = "";
        List<Log> logs = new List<Log>();

        public MainForm()
        {
            InitializeComponent();
        }

        private void SetLogFileName(string fileName)
        {
            if (!string.IsNullOrEmpty(fileName))
            {
                logfile = Path.GetFullPath(fileName);
                this.Text = $"日志浏览工具 [{logfile}]";
                logs = Log.LoadFromFile(logfile);

                cbTypes.Items.Clear();
                foreach (var item in logs.GroupBy(log => log.LogType))
                    cbTypes.Items.Add(item.Key);

                cbMethodNames.Items.Clear();
                foreach (var item in logs.GroupBy(log => log.MethodInfo))
                    cbMethodNames.Items.Add(item.Key);

                ShowLogs(logs);
            }
        }

        private void ShowLogs(List<Log> logs)
        {
            lvLogs.Items.Clear();
            lvLogs.SuspendLayout();
            lvLogs.BeginUpdate();
            foreach (Log log in logs)
            {
                lvLogs.Items.Add(new ListViewItem(log.ToStrings()));
                lvLogs.Items[lvLogs.Items.Count - 1].Tag = log;
            }
            lvLogs.EndUpdate();
            lvLogs.ResumeLayout();
        }

        private void TiOpenLog_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "*.log|*.log";
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                SetLogFileName(ofd.FileName);
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            SetLogFileName("..\\Logs\\20190608.log");
        }

        private void LvLogs_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvLogs.SelectedIndices.Count == 0)
                return;

            Log log = lvLogs.SelectedItems[0].Tag as Log;
            txtTime.Text = log.Time.ToString();
            txtType.Text = log.LogType.ToString();
            txtMethodName.Text = log.MethodInfo;
            lbArguments.Items.Clear();

            for (int i = 0; i < log.Arguments.Length; i++)
                lbArguments.Items.Add(log.Arguments[i]);

            lbArguments.SelectedIndex = log.Arguments.Length > 0 ? 0 : -1;
        }

        private void LbArguments_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lvLogs.SelectedIndices.Count == 0 || lbArguments.Items.Count == 0)
                return;

            Log log = lvLogs.SelectedItems[0].Tag as Log;
            txtArgContent.Text = log.Arguments[lbArguments.SelectedIndex];
        }

        private void BtnSearch_Click(object sender, EventArgs e)
        {
            List<Log> filterLogs = new List<Log>();
            filterLogs.AddRange(logs);

            if (cbTypes.Text.Length > 0)
            {
                for (int i = filterLogs.Count - 1; i >= 0; i--)
                    if (!filterLogs[i].LogType.ToString().Contains(cbTypes.Text))
                        filterLogs.RemoveAt(i);
            }

            if (cbMethodNames.Text.Length > 0)
            {
                for (int i = filterLogs.Count - 1; i >= 0; i--)
                    if (!filterLogs[i].MethodInfo.Contains(cbMethodNames.Text))
                        filterLogs.RemoveAt(i);
            }

            if (txtKeyWord.Text.Length > 0)
            {
                for (int i = filterLogs.Count - 1; i >= 0; i--)
                {
                    bool contained = false;
                    for (int j = 0; j < filterLogs[i].Arguments.Length; j++)
                    {
                        if (filterLogs[i].Arguments[j].Contains(txtKeyWord.Text))
                        {
                            contained = true;
                            break;
                        }
                    }
                    if (!contained)
                        filterLogs.RemoveAt(i);
                }
            }

            ShowLogs(filterLogs);
        }

        private void BtnReset_Click(object sender, EventArgs e)
        {
            cbTypes.Text = "";
            cbMethodNames.Text = "";
            txtKeyWord.Clear();
        }

        private void BtnCopyLog_Click(object sender, EventArgs e)
        {
            try
            {
                StreamReader sr = new StreamReader("abc.txt");
                sr.ReadToEnd();
                sr.Close();
            }
            catch (Exception ex)
            {
                AddLog(ex);
            }
        }

        private void BtnCopy_Click(object sender, EventArgs e)
        {
            try
            {
                string text = txtArgContent.Text;
                Clipboard.SetText(text);
                string str = txtArgContent.TextLength > 10 ? txtArgContent.Text.Substring(10) : txtArgContent.Text;
                MessageBox.Show($"左侧文本框的内容 \"{str}\" 已复制。", "复制完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                AddLog(ex);
            }
        }

        private void AddLog(Exception ex)
        {
            StackTrace trace = new StackTrace(ex);
            Console.WriteLine(trace.FrameCount);

            foreach (StackFrame sf in trace.GetFrames())
            {
                string info = string.Format("{0}->{1}_{2}@{3}:{4}",
                 sf.GetFileName(),                       // 文件名
                 sf.GetMethod().DeclaringType.FullName,  // 类全名
                 sf.GetMethod().Name,                    // 方法名
                 sf.GetFileLineNumber(),                 // 所在行号
                 sf.GetFileColumnNumber());              // 所有列号 
                Console.WriteLine(info + "\t" + ex.Message);
            }

            //StackFrame sf = trace.GetFrame(0);
            //string info = string.Format("{0}->{1}_{2}@{3}:{4}",
            //                 sf.GetFileName(),                       // 文件名
            //                 sf.GetMethod().DeclaringType.FullName,  // 类全名
            //                 sf.GetMethod().Name,                    // 方法名
            //                 sf.GetFileLineNumber(),                 // 所在行号
            //                 sf.GetFileColumnNumber());              // 所有列号 
            //Console.WriteLine(info + "\t" + ex.Message);
        }
    }
}
